home *** CD-ROM | disk | FTP | other *** search
/ PC World Komputer 2003 November A / PCWK1103A.iso / Adobe After Effects 6.0 tryout / MM5.Cab / F3693_email_methods.jsx.304FA6F7_2783_11D4_8520_00C04F602FD3 < prev    next >
Text File  |  2003-07-18  |  8KB  |  270 lines

  1. ∩╗┐// This file is encoded in UTF-8.
  2. //
  3. // This is generic code for talking to an email server.
  4. // Copyright 2003 Adobe Systems Inc.
  5.  
  6.  
  7.  
  8. // Create an email object. The function may be called both
  9. // as a global function and as a constructor. It takes the
  10. // name of the email server, and an optional Boolean that,
  11. // if true, prints debugging messages.
  12. // This object is not guaranteed to work for all SMTP servers,
  13. // some of them may require a different set of commands.
  14.  
  15. // functions:
  16. // send (fromAddress, toAddress, subject, text) - send an email
  17. // auth (name, pass) - do an authorization via POP3
  18. // both functions return false on errors
  19.  
  20. // sample:
  21. // e = new EmailSocket ("mail.host.com");
  22. // authorize via POP3 (not all servers require authorization)
  23. // e.auth ("myname", "mypass");
  24. // send the email
  25. // e.send ("me@my.com", "you@you.com", "My Subject", "Hi there!")
  26.  
  27. // This script makes use of the Socket object, and creates a new class
  28. // called EmailSocket that is derived from Socket. For more information on
  29. // creating new classes in this way, consult chapter 7 of JavaScript, The
  30. // Definitive Guide, by David Flanagan (O'Reilly).
  31. //
  32. // Version History:
  33. // V1 initial release
  34. // v2 - fix problems with bare linefeeds in the email that 
  35. //        caused it to be rejected by some servers. http://cr.yp.to/docs/smtplf.html
  36. // v3 - add support for the SMTP AUTH command. Only the LOGIN
  37. //    protocol is supported since it looks like all servers support
  38. //    it, while not all support PLAIN. Outlook Express 4.x and 5.x use
  39. //    LOGIN as there AUTH protocol.
  40. //    Also fix bug where EHLO sent a syntactically incorrect argument
  41.  
  42. //This is the constructor for the email socket. It takes as arguments:
  43. //server - the address of the email server (is not checked for validity here)
  44. //dbg - a boolean, if true, prints additional error information
  45.  
  46. function EmailSocket (server, dbg) {
  47.     var obj = new Socket;
  48.     obj._host = server;
  49.     obj._debug = (dbg == true);
  50.     obj.__proto__ = EmailSocket.prototype;
  51.     return obj;
  52. }
  53.  
  54. // correct the protoype chain to point to the Socket prototype chain
  55. // - this is what actually causes the derivation from Socket.
  56.  
  57. EmailSocket.prototype.__proto__ = Socket.prototype;
  58.  
  59. // This sets up the send() member function. send() takes as arguments:
  60. // from - the email address of the sender. This is not validated.
  61. // to - the email address of the recipient. If there is an error,
  62. // and the from address is incorrect, you will not be notified.
  63. // subject - the contents of the subject field.
  64. // text - the body of the message.
  65. // auth_user - OPTIONAL the username of the account to authorize with the smtp server
  66. // auth_password - OPTIONAL - the already base64 encoded password
  67. //
  68. // Returns: 
  69. // true if sending succeeded
  70. // THROWS AN ERROR STRING if the function fails.
  71. //
  72. //
  73. // Note that this code uses a local function object to create
  74. // the function that is assigned to send.
  75.  
  76. EmailSocket.prototype.send = function (from, to, subject, text, auth_user, auth_password) {
  77.     // open the socket on port 25 (SMTP)
  78.     // right now this is binary because otherwise the CRLF got reinterpreted and
  79.     // my server would not accept it. We will need changes to the socket object
  80.     // to fix correctly.
  81.     if (!this.open (this._host + ":25", "binary"))
  82.         return false;
  83.     try {
  84.         // discard the greeting
  85.         var greeting = this.read();
  86.         if (this._debug)
  87.             write ("RECV: " + greeting);
  88.         
  89.         // issue EHLO and other commands
  90.         // one user is having aproblem with the full email as the @ sign is illegal
  91.         // we should use the ip of the client http://cr.yp.to/smtp/helo.html#helo
  92.         // but we can't get that with the socket object. therefore we are using
  93.         // the host portion of the reply to email address.
  94.         var client_only = from.split("@")[1];
  95.         
  96.         this._SMTP ("EHLO " + client_only);
  97.         var response = this.read();
  98.         
  99.         if (auth_user) {
  100.             // now send the auth stuff
  101.             this._SMTP("AUTH LOGIN");
  102.             this._SMTP(this._ENCODE_BASE_64(auth_user));
  103.             this._SMTP(auth_password);
  104.         }
  105.         
  106.         this._SMTP ("MAIL FROM: " + from);
  107.         this._SMTP ("RCPT TO: " + to);
  108.         this._SMTP ("DATA");
  109.         // send subject and time stamp
  110.         this.writecrlfln ("From: " + from);
  111.         this.writecrlfln ("To: " + to);
  112.         this.writecrlfln ("Date: " + new Date().toString());
  113.         if (typeof subject != undefined)
  114.             this.writecrlfln ("Subject: " + subject);
  115.         this.writecrlfln();
  116.         // send the text
  117.         if (typeof text != undefined)
  118.             this.writecrlfln (text);
  119.         // terminate with a single dot and wait for response
  120.         this._SMTP (".");
  121.         // terminate the session
  122.         this._SMTP ("QUIT");
  123.         this.close();
  124.         return true;
  125.     }
  126.     catch (e) {
  127.         this.close();
  128.         throw e;
  129.     }
  130. }
  131.  
  132. // Authorize via POP3. Supply name and password.
  133. //
  134. // Returns: 
  135. // true if sending succeeded
  136. // false otherwise (if there was an error)
  137. //
  138. // Arguments:
  139. // name - the userName of the account
  140. // pass - the password
  141.  
  142. EmailSocket.prototype.auth = function (name, pass) {
  143.     // open the connection on port 110 (POP3)
  144.     if (!this.open (this._host + ":110"))
  145.         return false;
  146.     try {
  147.         // discard the greeting
  148.         var greeting = this.read();
  149.         if (this._debug)
  150.             write ("RECV: " + greeting);
  151.         // issue POP3 commands
  152.         this._POP3 ("USER " + name);
  153.         this._POP3 ("PASS " + pass);
  154.         this._POP3 ("QUIT");
  155.         this.close();
  156.         return true;
  157.     }
  158.     catch (e) {
  159.         this.close();
  160.         return false;
  161.     }
  162. }
  163.  
  164. // Users of the EmailSocket do not need to be concerned with
  165. // the following method. It is an implementation helper.
  166.  
  167. // local function to send a command & check a POP3 reply
  168. // throws in case of error
  169. EmailSocket.prototype._POP3 = function (cmd) {
  170.     if (this._debug)
  171.         writeLn ("SEND: " + cmd);
  172.     if (!this.writecrlfln (cmd))
  173.         throw "Error";
  174.     var reply = this.read();
  175.     if (this._debug)
  176.         write ("RECV: " + reply);
  177.     // the reply starts by either + or -
  178.     if (reply [0] == "+")
  179.         return;
  180.     throw "Error";
  181. }
  182.  
  183. // Users of the EmailSocket do not need to be concerned with
  184. // the following method. It is an implementation helper.
  185.  
  186. // local function to send a command & check a SMTP reply
  187. // throws in case of error
  188. EmailSocket.prototype._SMTP = function (cmd) {
  189.     if (this._debug) 
  190.         writeLn ("SEND: " + cmd);
  191.     if (!this.writecrlfln (cmd))
  192.         throw "Error";
  193.     var reply = this.read();
  194.     if (this._debug)
  195.         write ("RECV: " + reply);
  196.     // the reply is a three-digit code followed by a space
  197.     var match = reply.match (/^(\d{3})\s/m);
  198.     if (match.length == 2) {
  199.         var n = Number (match [1]);
  200.         if (n >= 200 && n <= 399)
  201.             return;
  202.     }
  203.     throw reply;
  204. }
  205.  
  206. // email can't contain bare linefeeds: http://cr.yp.to/docs/smtplf.html
  207. EmailSocket.prototype.writecrlfln = function (cmd) {
  208.     if (cmd) {
  209.         return this.write(cmd + "\r\n");
  210.     } else {
  211.         return this.write("\r\n");
  212.     }
  213. }
  214.  
  215.  
  216.  
  217. // This base64 encodes str. RFC-2045
  218. EmailSocket.prototype._ENCODE_BASE_64 = function(str)
  219. {
  220.     var lut = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
  221.     
  222.     var chunk = 0;
  223.         
  224.     var result = "";
  225.             
  226.     for( var i = 0; i < str.length; i += 3) {
  227.         chunk = str.charCodeAt(i) & 0xFF;
  228.         chunk = chunk << 8;
  229.     
  230.         // asking for a char out of range returns ""
  231.         chunk |= str.charCodeAt(i+1) & 0xFF;
  232.         chunk = chunk << 8;
  233.  
  234.         chunk |= str.charCodeAt(i+2) & 0xFF;
  235.  
  236.         // these are the number of gaps until we hit %3
  237.         var partialEnd = 3 - (str.length - i) ;
  238.         
  239.         var num6bits = 4;
  240.         // 
  241.         if (partialEnd == 2) { // one character encoded
  242.             num6bits = 2;
  243.         } else if (partialEnd == 1) { // two encoded
  244.             num6bits = 3;
  245.         }
  246.         
  247.         for( var j = 0; j < num6bits; j++){
  248.             result += lut.charAt((chunk & 0xFC0000) >> 18); // six bits    
  249.             chunk = chunk << 6; 
  250.         }    
  251.         
  252.         // fill with = chars
  253.         if (partialEnd < 3) {
  254.             for( var j = 0; j < partialEnd; j++){
  255.                 result += "=";
  256.             }
  257.         }
  258.     }
  259.     
  260.     return result;
  261. }
  262.  
  263. // nice to have: a toString()
  264. // This function allows the email object to be printed.
  265.  
  266. EmailSocket.prototype.toString = function() {
  267.     return "[object Email]";
  268. }
  269.  
  270.